package com.hsurosy.hsuchain.nft.notice.job;

import com.hsurosy.hsuchain.nft.notice.domain.constant.NoticeState;
import com.hsurosy.hsuchain.nft.notice.domain.entity.Notice;
import com.hsurosy.hsuchain.nft.notice.domain.service.NoticeService;
import com.hsurosy.hsuchain.nft.sms.SmsService;
import com.hsurosy.hsuchain.nft.sms.response.SmsSendResponse;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 通知重试任务
 *
 * @Author Hsu琛君珩
 * @Date 2024-10-05 16:58
 * @Description
 * @Version: v1.0.0
 */
@Component
public class NoticeSendRetryJob {

    /**
     * 通知服务，用于查询和更新通知状态
     */
    @Autowired
    private NoticeService noticeService;

    /**
     * 短信服务，用于重新发送通知
     */
    @Autowired
    private SmsService smsService;

    /**
     * 每页查询的通知数量
     */
    private static final int PAGE_SIZE = 100;

    /**
     * 日志记录器，用于输出任务执行过程中的日志
     */
    private static final Logger LOG = LoggerFactory.getLogger(NoticeSendRetryJob.class);

    /**
     * XXL-Job 任务入口
     *
     * 定义了一个名为 noticeSendRetryJob 的XXL-Job任务，重试发送失败的通知。
     *
     * @return ReturnT<String> 表示任务执行结果
     */
    @XxlJob("noticeSendRetryJob")
    public ReturnT<String> execute() {

        int currentPage = 1;
        // 分页查询待重试的通知
        Page<Notice> page = noticeService.pageQueryForRetry(currentPage, PAGE_SIZE);

        // 遍历当前页的通知并重试发送
        page.getRecords().forEach(this::executeSingle);

        // 如果还有下一页，则继续分页查询并执行重试
        while (page.hasNext()) {
            currentPage++;
            page = noticeService.pageQueryForRetry(currentPage, PAGE_SIZE);
            page.getRecords().forEach(this::executeSingle);
        }

        // 任务执行成功
        return ReturnT.SUCCESS;
    }

    /**
     * 单个通知的重试逻辑
     *
     * @param notice 通知对象
     */
    private void executeSingle(Notice notice) {
        LOG.info("开始重试发送通知，通知ID为 {}", notice.getId());

        // 调用短信服务重新发送通知
        SmsSendResponse result = smsService.sendMsg(notice.getTargetAddress(), notice.getNoticeContent());

        // 根据发送结果更新通知状态
        if (result.getSuccess()) {
            notice.setState(NoticeState.SUCCESS);
            notice.setSendSuccessTime(new Date());
            notice.setLockVersion(1);
        } else {
            notice.setState(NoticeState.FAILED);
            notice.setLockVersion(1);
            // 记录发送失败的详细信息
            notice.addExtendInfo("executeResult", JSON.toJSONString(result));
        }

        // 更新通知信息
        noticeService.updateById(notice);
    }
}
